import 'dart:math';

import 'package:flutter/material.dart';
import '../bezier_curve/bezier_util.dart';

class MaskFilterDemo extends StatefulWidget {
  @override
  _MaskFilterDemoState createState() => _MaskFilterDemoState();
}

class _MaskFilterDemoState extends State<MaskFilterDemo>
    with SingleTickerProviderStateMixin {
  late Animation<double> animation;
  late AnimationController controller;

  void initState() {
    super.initState();
    controller =
        AnimationController(duration: const Duration(seconds: 1), vsync: this);
    animation = Tween<double>(begin: 0, end: 1.0).animate(CurvedAnimation(
      parent: controller,
      curve: Curves.linear,
    ))
      ..addListener(() {
        setState(() {});
      });
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
        child: CustomPaint(
          painter: MaskFilterPainter(
            animationValue: animation.value,
          ),
        ),
        onTap: () {
          controller.repeat();
          // if (controller.status == AnimationStatus.completed) {
          //   controller.reverse();
          // } else {
          //   controller.forward();
          // }
        });
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }
}

class MaskFilterPainter extends CustomPainter {
  double animationValue;
  MaskFilterPainter({required this.animationValue});

  @override
  void paint(Canvas canvas, Size size) {
    var paint = Paint();
    paint.style = PaintingStyle.fill;
    //_drawMovingCircle(canvas, size, paint);
    //_drawMultiMovingRect(canvas, size, paint);
    //_drawMultiMovingCircle(canvas, size, paint);
    _drawRectsUsingBezier(canvas, size, paint);
    // 效果对比绘制
    // var center = Offset(size.width / 2, size.height / 2);
    // var radius = 80.0;
    // paint.color = Colors.blue[400]!;
    // paint.maskFilter = MaskFilter.blur(BlurStyle.outer, 20.0);
    // canvas.drawCircle(center, radius, paint);
  }

  void _drawMovingCircle(Canvas canvas, Size size, Paint paint) {
    var radius = 80.0;
    paint.shader = LinearGradient(
      begin: Alignment.topCenter,
      end: Alignment.bottomCenter,
      colors: [
        Colors.black87,
        Colors.purple,
        Colors.blue,
        Colors.green,
        Colors.yellow[500]!,
        Colors.orange,
        Colors.red[400]!
      ].reversed.toList(),
      tileMode: TileMode.clamp,
      transform: GradientRotation(
        animationValue * 2 * pi,
      ),
    ).createShader(Offset(0, 0) & size);

    paint.maskFilter = MaskFilter.blur(BlurStyle.solid, 20.0);
    canvas.drawCircle(
        Offset(size.width / 2, size.height * animationValue), radius, paint);
  }

  void _drawMultiMovingRect(Canvas canvas, Size size, Paint paint) {
    paint.shader = LinearGradient(
      begin: Alignment.topCenter,
      end: Alignment.bottomCenter,
      colors: [
        Colors.black87,
        Colors.purple,
        Colors.blue,
        Colors.green,
        Colors.yellow[500]!,
        Colors.orange,
        Colors.red[400]!
      ].reversed.toList(),
      tileMode: TileMode.clamp,
      transform: GradientRotation(
        animationValue * 2 * pi,
      ),
    ).createShader(Offset(0, 0) & size);

    paint.maskFilter = MaskFilter.blur(BlurStyle.solid, 20.0);
    var count = 10;
    for (var i = 0; i < count + 1; ++i) {
      canvas.drawRect(
        Offset(size.width / count * i, size.height * animationValue) &
            Size(size.width / count, size.width / count * 2),
        paint,
      );
    }
  }

  void _drawMultiMovingCircle(Canvas canvas, Size size, Paint paint) {
    paint.shader = LinearGradient(
      begin: Alignment.topCenter,
      end: Alignment.bottomCenter,
      colors: [
        Colors.black87,
        Colors.purple,
        Colors.blue,
        Colors.green,
        Colors.yellow[500]!,
        Colors.orange,
        Colors.red[400]!
      ].reversed.toList(),
      tileMode: TileMode.clamp,
      transform: GradientRotation(
        animationValue * 2 * pi,
      ),
    ).createShader(Offset(0, 0) & size);

    paint.maskFilter = MaskFilter.blur(BlurStyle.outer, 20.0);
    var count = 10;
    for (var i = 0; i < count + 1; ++i) {
      canvas.drawCircle(
        Offset(size.width * i / count * animationValue,
            size.height * i / count * animationValue),
        size.width / count,
        paint,
      );
    }
  }

  void _drawRectsUsingBezier(Canvas canvas, Size size, Paint paint) {
    paint.shader = LinearGradient(
      begin: Alignment.topCenter,
      end: Alignment.bottomCenter,
      colors: [
        Colors.black87,
        Colors.purple,
        Colors.blue,
        Colors.green,
        Colors.yellow[500]!,
        Colors.orange,
        Colors.red[400]!
      ].reversed.toList(),
      tileMode: TileMode.clamp,
      transform: GradientRotation(
        animationValue * 2 * pi,
      ),
    ).createShader(Offset(0, 0) & size);

    paint.maskFilter = MaskFilter.blur(BlurStyle.outer, 2);
    final height = 120.0;
    var p0 = Offset(0, size.height / 2 + height);
    var p1 = Offset(size.width / 4, size.height / 2 - height);
    var p2 = Offset(size.width * 3 / 4, size.height / 2 + height);
    var p3 = Offset(size.width, size.height / 2 - height);
    var count = 150;
    var squareSize = 20.0;
    for (var t = 1; t <= count; t += 1) {
      var curvePoint =
          BezierUtil.get3OrderBezierPoint(p0, p1, p2, p3, t / count);

      canvas.drawRect(
        curvePoint & Size(squareSize, squareSize),
        paint,
      );
    }

    for (var t = 1; t <= count; t += 1) {
      var curvePoint =
          BezierUtil.get3OrderBezierPoint(p3, p1, p2, p0, t / count);

      canvas.drawRect(
        curvePoint & Size(squareSize, squareSize),
        paint,
      );
    }
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return true;
  }
}
